#include "stdafx.h"
#include "InteractManager.h"
#include "Objects\ObjectManager.h"
#include "World\ChunkManager.h"
#include "World\Chunk.h"
#include "Objects\GameObject.h"
#include "IInteractable.h"
#include "Delegate.h"
#include "Objects\Player\Player.h"
#include "Objects\ControlableGameObject.h"
#include "World\WorldEvents.h"
#include "..\EdgeControls\Input.h"
#include "..\EdgeControls\Controls.h"

void OnObjectAdded(void**);
void OnObjectRemoved(void**);

void OnInteract(void**);


InteractManager::InteractManager(void)
{
	Input* pInput = Input::GetInstance();

	pInput->getKeyBindings(Controls::GetInstance().interact)->Subscribe(Functor<key_event_handler>(&OnInteract, 0));

	WorldEvents::ObjectCreated->Subscribe(Functor<world_event_handler>(&OnObjectAdded, 0));
	WorldEvents::ObjectDestroyed->Subscribe(Functor<world_event_handler>(&OnObjectRemoved, 0));
}


/*virtual*/ InteractManager::~InteractManager(void)
{
	// release all base game components (if any)
	for (unsigned int i = 0; i < interactors.size(); i++)
	{
		BaseGameComponent* obj = dynamic_cast<BaseGameComponent*>(interactors[i]);
		if (obj)
			obj->Release();
	}
}

void InteractManager::Update(float dt)
{
	
}

void InteractManager::Draw(void)
{

}

void InteractManager::RemoveInteractor(IInteractable* interactor)
{
	for (unsigned int i = 0; i < interactors.size(); i++)
		if (interactors[i] == interactor)
			interactors.erase(interactors.begin() + i);
}


void InteractManager::AddInteractor(IInteractable* interactor)
{
	if (dynamic_cast<BaseGameComponent*>(interactor))
	{
		BaseGameComponent* comp = (BaseGameComponent*)interactor;
		comp->AddRef();
	}
	interactors.push_back(interactor);
}

void OnObjectAdded(void** params)
{
	GameObject* object = (GameObject*)params[0];

	// if the object is an IInteractable, add it into interactors
	if (dynamic_cast<IInteractable*>(object))
	{
		object->AddRef();
		InteractManager::GetInstance()->AddInteractor(dynamic_cast<IInteractable*>(object));
	}
}

void OnObjectRemoved(void** params)
{
	GameObject* object = (GameObject*)(params[0]);

	if (dynamic_cast<IInteractable*>(object))
	{
		InteractManager::GetInstance()->RemoveInteractor((IInteractable*)object);
	}
}

void OnInteract(void** params)
{
	// find an interactor near the player and interact with it
	for (unsigned int i = 0; i < InteractManager::GetInstance()->getNumInteractors(); i++)
	{
		IInteractable* interactor = InteractManager::GetInstance()->getInteractor(i);

		Vector3 player_pos = Player::GetInstance()->getTarget()->getPosition();
		float distance = VectorHelper::distance(player_pos, interactor->getLocation());
		if (distance < interactor->getRange())
			interactor->Interact();
	}
}